﻿using System;
using System.Collections.Specialized;
using System.Web.Hosting;
using System.Web.Security;
using InfoSite.Data;
using InfoSite.Tools;

namespace InfoSite.SiteMembership.Provider
{
	public class SiteMembershipProvider : MembershipProvider
	{
		#region Properties

		private bool _enablePasswordRetrieval;
		public override bool EnablePasswordRetrieval
		{
			get { return _enablePasswordRetrieval; }
		}

		private bool _enablePasswordReset;
		public override bool EnablePasswordReset
		{
			get { return _enablePasswordReset; }
		}

		private string _applicationName;
		public override string ApplicationName
		{
			get { return _applicationName; }
			set { _applicationName = value; }
		}

		private int _maxInvalidPasswordAttempts;
		public override int MaxInvalidPasswordAttempts
		{
			get { return _maxInvalidPasswordAttempts; }
		}

		private int _minRequiredNonAlphanumericCharacters;
		public override int MinRequiredNonAlphanumericCharacters
		{
			get { return _minRequiredNonAlphanumericCharacters; }
		}

		private int _minRequiredPasswordLength;
		public override int MinRequiredPasswordLength
		{
			get { return _minRequiredPasswordLength; }
		}

		private int _passwordAttemptWindow;
		public override int PasswordAttemptWindow
		{
			get { return _passwordAttemptWindow; }
		}

		private MembershipPasswordFormat _passwordFormat;
		public override MembershipPasswordFormat PasswordFormat
		{
			get { return _passwordFormat; }
		}

		private string _passwordStrengthRegularExpression;
		public override string PasswordStrengthRegularExpression
		{
			get { return _passwordStrengthRegularExpression; }
		}

		private bool _requiresQuestionAndAnswer;
		public override bool RequiresQuestionAndAnswer
		{
			get { return _requiresQuestionAndAnswer; }
		}

		private bool _requiresUniqueEmail;
		public override bool RequiresUniqueEmail
		{
			get { return _requiresUniqueEmail; }
		}

		#endregion

		public override void Initialize(string name, NameValueCollection config)
		{
			if (config == null)
				throw new ArgumentNullException("config");

			if (String.IsNullOrEmpty(name))
				name = "HmtMembershipProvider";

			if (String.IsNullOrEmpty(config["description"]))
			{
				config.Remove("description");
				config.Add("description", "Custom Membership Provider");
			}

			base.Initialize(name, config);

			_applicationName = GetConfigValue(config["applicationName"], HostingEnvironment.ApplicationVirtualPath);
			_maxInvalidPasswordAttempts = Convert.ToInt32(GetConfigValue(config["maxInvalidPasswordAttempts"], "5"));
			_passwordAttemptWindow = Convert.ToInt32(GetConfigValue(config["passwordAttemptWindow"], "10"));
			_minRequiredNonAlphanumericCharacters = Convert.ToInt32(GetConfigValue(config["minRequiredNonalphanumericCharacters"], "1"));
			_minRequiredPasswordLength = Convert.ToInt32(GetConfigValue(config["minRequiredPasswordLength"], "6"));
			_enablePasswordReset = Convert.ToBoolean(GetConfigValue(config["enablePasswordReset"], "true"));
			_passwordStrengthRegularExpression = Convert.ToString(GetConfigValue(config["passwordStrengthRegularExpression"], ""));
		}

		private string GetConfigValue(string configValue, string defaultValue)
		{
			return String.IsNullOrEmpty(configValue) ? defaultValue : configValue;
		}

		public override bool ChangePassword(string email, string sOldPassword, string sNewPassword)
		{
			if (MembershipHelper.MembershipService.ValidateUser(email, sOldPassword))
			{
				SiteUser siteUser = SiteUser.SearchByEmail(email);
				if (siteUser != null && siteUser.LastModifiedDate != null)
				{
					DateTime dtLastModifiedDate = siteUser.LastModifiedDate.Value;

					siteUser.PasswordSalt = CryptoHelper.CreateSalt();
					siteUser.Password = CryptoHelper.CreatePasswordHash(sNewPassword, siteUser.PasswordSalt);

					siteUser.UpdateInstance();

					siteUser = SiteUser.SearchByEmail(email);

					return siteUser.LastModifiedDate > dtLastModifiedDate;
				}
			}
			return false;
		}

		public override bool ChangePasswordQuestionAndAnswer(string username,
															 string password,
															 string newPasswordQuestion,
															 string newPasswordAnswer)
		{
			throw new NotImplementedException();
		}

		public override MembershipUser CreateUser(string username,
												  string password,
												  string email,
												  string passwordQuestion,
												  string passwordAnswer,
												  bool isApproved,
												  object providerUserKey,
												  out MembershipCreateStatus status)
		{
			UserRepository userRepository = new UserRepository();

			MembershipUser membershipUser = userRepository.CreateUser(username, password, email, isApproved);
			status = MembershipCreateStatus.Success;

			return membershipUser;
		}

		public override bool DeleteUser(string email, bool deleteAllRelatedData)
		{
			SiteUser siteUser = SiteUser.SearchByEmail(email);
			if (siteUser != null)
			{
				siteUser.MarkAsDeleted();
				return true;
			}
			return false;
		}

		public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
		{
			throw new NotImplementedException();
		}

		public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
		{
			throw new NotImplementedException();
		}

		public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
		{
			throw new NotImplementedException();
		}

		public override int GetNumberOfUsersOnline()
		{
			throw new NotImplementedException();
		}

		public override string GetPassword(string username, string answer)
		{
			throw new NotImplementedException();
		}

		public override MembershipUser GetUser(string email, bool userIsOnline)
		{
			SiteUser dbuser = SiteUser.SearchByEmail(email);

			if (dbuser != null && dbuser.UserId != null && dbuser.IsActivated != null && dbuser.IsLockedOut != null && dbuser.CreatedDate != null && dbuser.LastLoginDate != null && dbuser.LastLockedOutDate != null)
			{
				int providerUserKey = dbuser.UserId.Value;
				string passwordQuestion = string.Empty;
				string comment = dbuser.Comments;
				bool isApproved = dbuser.IsActivated.Value;
				bool isLockedOut = dbuser.IsLockedOut.Value;
				DateTime creationDate = dbuser.CreatedDate.Value;
				DateTime lastLoginDate = dbuser.LastLoginDate.Value;
				DateTime lastActivityDate = DateTime.Now;
				DateTime lastPasswordChangedDate = DateTime.Now;
				DateTime lastLockedOutDate = dbuser.LastLockedOutDate.Value;

				MembershipUser user = new MembershipUser("HmtMembershipProvider",
														 email,
														 providerUserKey,
														 email,
														 passwordQuestion,
														 comment,
														 isApproved,
														 isLockedOut,
														 creationDate,
														 lastLoginDate,
														 lastActivityDate,
														 lastPasswordChangedDate,
														 lastLockedOutDate);

				return user;
			}
			return null;
		}

		public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
		{
			throw new NotImplementedException();
		}

		public override string GetUserNameByEmail(string email)
		{
			SiteUser siteUser = SiteUser.SearchByEmail(email);
			return siteUser != null ? siteUser.UserName : String.Empty;
		}

		public override string ResetPassword(string email, string answer)
		{
			SiteUser siteUser = SiteUser.SearchByEmail(email);
			if (siteUser == null)
				return String.Empty;

			string sNewPassword = Membership.GeneratePassword(8, 0);

			siteUser.PasswordSalt = CryptoHelper.CreateSalt();
			siteUser.Password = CryptoHelper.CreatePasswordHash(sNewPassword, siteUser.PasswordSalt);
			siteUser.NewPasswordRequested = DateTime.Now;

			siteUser.UpdateInstance();

			return sNewPassword;
		}

		public override bool UnlockUser(string userName)
		{
			throw new NotImplementedException();
		}

		public override void UpdateUser(MembershipUser user)
		{
			throw new NotImplementedException();
		}

		public override bool ValidateUser(string email, string password)
		{
			SiteUser dbuser = SiteUser.SearchByEmail(email);
			return dbuser != null &&
				   dbuser.IsLockedOut.HasValue && !dbuser.IsLockedOut.Value &&
				   dbuser.IsDeleted.HasValue && !dbuser.IsDeleted.Value &&
				   dbuser.IsActivated.HasValue && dbuser.IsActivated.Value &&
				   dbuser.Password == CryptoHelper.CreatePasswordHash(password, dbuser.PasswordSalt);
		}
	}
}